package com.common.web;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

public class GzipResponseStream extends ServletOutputStream {

    protected ByteArrayOutputStream out;
    protected ServletOutputStream servletOut;
    protected GZIPOutputStream gzipOut;
    protected HttpServletResponse httpResponse;
    protected boolean closed;

    public GzipResponseStream(HttpServletResponse httpResponse)
            throws IOException {
        out = new ByteArrayOutputStream();
        gzipOut = new GZIPOutputStream(out);
        servletOut = httpResponse.getOutputStream();
        this.httpResponse = httpResponse;
        closed = false;
    }

    @Override
    public void close() throws IOException {
        if (closed) {
            // TODO
            // throw new IOException("This output stream has already been closed");
        } else {
            gzipOut.finish();
            byte[] abyte0 = out.toByteArray();
            httpResponse.addHeader("Content-Length", Integer
                    .toString(abyte0.length));
            httpResponse.addHeader("Content-Encoding", "gzip");
            servletOut.write(abyte0);
            servletOut.flush();
            servletOut.close();
            closed = true;

            return;
        }
    }

    @Override
    public void flush() throws IOException {
        if (closed) {
            throw new IOException("Cannot flush a closed output stream");
        } else {
            gzipOut.flush();

            return;
        }
    }

    @Override
    public void write(int i) throws IOException {
        if (closed) {
            throw new IOException("Cannot write to a closed output stream");
        } else {
            gzipOut.write((byte) i);

            return;
        }
    }

    @Override
    public void write(byte[] bytes) throws IOException {
        write(bytes, 0, bytes.length);
    }

    @Override
    public void write(byte[] bytes, int i, int j) throws IOException {
        if (closed) {
            throw new IOException("Cannot write to a closed output stream");
        } else {
            gzipOut.write(bytes, i, j);

            return;
        }
    }

    public boolean closed() {
        return closed;
    }

    public void reset() {}

}
